package com.tuniu.agents.impl.hotel;

import com.tuniu.agents.advisor.ChatEnvironmentMemory;
import com.tuniu.agents.agent.Agent;
import com.tuniu.agents.agent.AgentManagerGroup;
import com.tuniu.agents.common.agent.SelectionAgent;
import com.tuniu.agents.common.i18n.I18nConstants;
import com.tuniu.agents.common.message.BaseAgentNewResp;
import com.tuniu.agents.common.message.CardTypeEnum;
import com.tuniu.agents.memory.MemoryManager;
import com.tuniu.agents.message.MessageLogger;
import com.tuniu.agents.message.MessageRender;
import com.tuniu.agents.tools.hotel.constant.HotelI18KeyConstants;
import com.tuniu.agents.tools.hotel.tool.HotelDetail;
import com.tuniu.agents.tools.hotel.tool.NlowestPriceHotelList;
import com.tuniu.agents.tools.hotel.tool.PlowestPriceHotelList;
import com.tuniu.agents.util.ChatResponseUtils;
import com.tuniu.agents.util.I18nUtil;
import com.tuniu.agents.util.JsonUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import reactor.core.publisher.Flux;

import java.util.Collections;
import java.util.List;
import java.util.Map;

public class HotelAgent extends SelectionAgent {

    private static final Logger log = LoggerFactory.getLogger(HotelAgent.class);

    public static final String AGENT_ID = "HotelAgent";

    protected final ChatEnvironmentMemory chatEnvironmentMemory;

    private MemoryManager memoryManager;

    private MessageRender messageRender;

    public HotelAgent(AgentManagerGroup agentManagerGroup,
                      String agentId, String promptTemplateId, MessageLogger logger, String... tools) {

        super(agentManagerGroup, agentId, promptTemplateId, logger, null, tools);
        this.chatEnvironmentMemory = agentManagerGroup.getChatEnvironmentMemory();
        this.memoryManager = agentManagerGroup.getMemoryManager();
        this.messageRender = agentManagerGroup.getMessageRender();
    }

    @Override
    public Flux<String> stream(String conversationId, List<Message> messages, Map<String, Object> context) {
        String message = messages.get(0).getText();
        ChatResponse chatResponse = this.callResponse(conversationId, message);
        String toolName = ChatResponseUtils.getFirstToolName(chatResponse);
        if (!StringUtils.hasText(toolName)) {
            return Flux.just(ChatResponseUtils.getFirstTextMessage(chatResponse));
        }else {
            String toolResponse = ChatResponseUtils.getFirstTextMessage(chatResponse);
            if (!StringUtils.hasText(toolResponse) || toolResponse.equals("null")) {
                log.error("hotel agent toolResponse fail:{}", toolResponse);
                return Flux.just(BaseAgentNewResp.sendAnswerMsg(null, I18nUtil.getMessage(conversationId,I18nConstants.COMMON_SYSTEM_ERROR_MESSAGE_KEY)));
            }
            Agent parseDataAgent = null;
            switch (toolName) {
                case NlowestPriceHotelList.TOOLNAME:
                    parseDataAgent = agentManager.getAgent(HotelAgentConfig.HOTEL_POI_LIST_PARSE_DATA);
                    break;
                case PlowestPriceHotelList.TOOLNAME:
                    parseDataAgent = agentManager.getAgent(HotelAgentConfig.HOTEL_PACKAGE_LIST_PARSE_DATA);
                    break;
                case HotelDetail.TOOLNAME:
                    // No need to pass to the large model for further analysis
                    HotelDetail.Response response = JsonUtil.fromJson(toolResponse, HotelDetail.Response.class);
                    if (CollectionUtils.isEmpty(response.rooms())) {
                        return Flux.just(BaseAgentNewResp.sendAnswerMsg(null,I18nUtil.getMessage(conversationId, HotelI18KeyConstants.HOTEL_DETAIL_ERROR_MESSAGE)));
                    }

                    Map<String, Object> hotelDataMap = JsonUtil.toMap(JsonUtil.toJson(response));
                    String acceptLanguage = I18nUtil.getLocaleLanguageTag(conversationId);
                    String markdownResponse = messageRender.renderTemplate("hotel/hotel-detail.ftlh",Map.of(I18nConstants.LANGUAGE_TAG, acceptLanguage), hotelDataMap);
                    String result = BaseAgentNewResp.sendCardMsg(CardTypeEnum.HOTEL_DETAIL.getCardType(), Collections.singletonList(response), markdownResponse, null);
                    String hotelDetailMarkdown = HotelDetail.buildHotelDetailMarkdown(response);
                    if (StringUtils.hasText(hotelDetailMarkdown)) {
                        // Store the basic information of the card in markdown format in the conversation record
                        memoryManager.setMessageRight(conversationId, Collections.singletonList(new AssistantMessage(hotelDetailMarkdown, Map.of("agentId", this.agentId))));
                    }
                    return Flux.just(result);
            }
            if (parseDataAgent == null) {
                log.error("hotel agent get parseDataAgent fail, toolName{}", toolName);
                return Flux.just(BaseAgentNewResp.sendAnswerMsg(null, I18nUtil.getMessage(conversationId,I18nConstants.COMMON_SYSTEM_ERROR_MESSAGE_KEY)));
            }
            return parseDataAgent.stream(conversationId, toolResponse);
        }
    }
}